home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / m4-1_0_3.lha / m4-1.0.3 / input.c < prev    next >
C/C++ Source or Header  |  1992-12-19  |  18KB  |  732 lines

  1. /*
  2.  * GNU m4 -- A simple macro processor
  3.  * Copyright (C) 1989-1992 Free Software Foundation, Inc.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /*
  21.  * Handling of different input sources, and lexical analysis.
  22.  */
  23.  
  24. #include "m4.h"
  25. /*
  26.  * Unread input can be either files, that should be read (eg. included
  27.  * files), strings, which should be rescanned (eg. macro expansion
  28.  * text), or quoted macro definitions (as returned by the builtin
  29.  * "defn").  Unread input are organised in a stack, implemented with an
  30.  * obstack.  Each input source is described by a "struct input_block".
  31.  * The obstack is "input_stack".  The top of the input stack is "isp".
  32.  *
  33.  * The macro "m4wrap" places the text to be saved on another input
  34.  * stack, on the obstack "wrapup_stack", whose top is "wsp".  When EOF
  35.  * is seen on normal input (eg, when "input_stack" is empty), input is
  36.  * switched over to "wrapup_stack".  To make this easier, all references
  37.  * to the current input stack, whether it be "input_stack" or
  38.  * "wrapup_stack", are done through a pointer "current_input", which
  39.  * points to either "input_stack" or "wrapup_stack".
  40.  *
  41.  * Pushing new input on the input stack is done by push_file (),
  42.  * push_string (), push_wrapup () (for wrapup text), and push_macro () (for
  43.  * macro definitions).  Because macro expansion needs direct access to
  44.  * the current input obstack (for optimisation), push_string () are split
  45.  * in two functions, push_string_init (), which returns a pointer to the
  46.  * current input stack, and push_string_finish (), which return a pointer
  47.  * to the final text.  The input_block *next is used to manage the
  48.  * coordination between the different push routines.
  49.  *
  50.  * The current file and line number are stored in two global variables,
  51.  * for use by the error handling functions in m4.c.  Whenever a file
  52.  * input_block is pushed, the current file name and line number is saved
  53.  * in the input_block, and the two variables are reset to match the new
  54.  * input file.
  55.  */
  56.  
  57. enum input_type
  58. {
  59.   INPUT_FILE,
  60.   INPUT_STRING,
  61.   INPUT_MACRO
  62. };
  63.  
  64. typedef enum input_type input_type;
  65.  
  66. struct input_block
  67. {
  68.   struct input_block *prev;    /* previous input_block on the input stack */
  69.   input_type type;        /* INPUT_FILE, INPUT_STRING or INPUT_MACRO */
  70.   union
  71.     {
  72.       struct
  73.     {
  74.       char *string;        /* string value */
  75.     }
  76.       u_s;
  77.       struct
  78.     {
  79.       FILE *file;        /* input file handle */
  80.       char *name;        /* name of PREVIOUS input file */
  81.       int lineno;        /* current line number for do. */
  82.       /* Yet another attack of "The curse of global variables" (sic).  */
  83.       int out_lineno;    /* current output line number do.*/
  84.       boolean advance_line;    /* start_of_input_line from advance_input */
  85.     }
  86.       u_f;
  87.       struct
  88.     {
  89.       builtin_func *func;    /* pointer to macros function */
  90.       boolean traced;    /* TRUE iff builtin is traced */
  91.     }
  92.       u_m;
  93.     }
  94.   u;
  95. };
  96.  
  97. typedef struct input_block input_block;
  98.  
  99.  
  100. /* Current input file name.  */
  101. char *current_file;
  102.  
  103. /* Current input line number.  */
  104. int current_line;
  105.  
  106. /* Obstack for storing individual tokens.  */
  107. static struct obstack token_stack;
  108.  
  109. /* Normal input stack.  */
  110. static struct obstack input_stack;
  111.  
  112. /* Wrapup input stack.  */
  113. static struct obstack wrapup_stack;
  114.  
  115. /* Input or wrapup.  */
  116. static struct obstack *current_input;
  117.  
  118. /* Bottom of token_stack, for obstack_free.  */
  119. static char *token_bottom;
  120.  
  121. /* Pointer to top of current_input.  */
  122. static input_block *isp;
  123.  
  124. /* Pointer to top of wrapup_stack.  */
  125. static input_block *wsp;
  126.  
  127. /* Aux. for handling split push_string ().  */
  128. static input_block *next;
  129.  
  130. /* Flag for advance_input to increment current_line.  */
  131. static boolean start_of_input_line;
  132.  
  133. #define CHAR_EOF    256    /* character return on EOF */
  134. #define CHAR_MACRO    257    /* character return for MACRO token */
  135.  
  136. /* Quote chars.  */
  137. char *rquote;
  138. char *lquote;
  139.  
  140. /* And their length.  */
  141. int len_rquote;
  142. int len_lquote;
  143.  
  144. /* And default quote chars.  */
  145. static char *def_rquote = DEF_RQUOTE;
  146. static char *def_lquote = DEF_LQUOTE;
  147.  
  148. /* And comment chars.  */
  149. char *bcomm;
  150. char *ecomm;
  151.  
  152. /* And their length.  */
  153. static int len_bcomm;
  154. static int len_ecomm;
  155.  
  156. /* And default comment chars.  */
  157. static char *def_bcomm = DEF_BCOMM;
  158. static char *def_ecomm = DEF_ECOMM;
  159.  
  160.  
  161. /*
  162.  * push_file () pushes an input file on the input stack, saving the
  163.  * current file name and line number.  If next is non-NULL, this push
  164.  * invalidates a call to push_string_init (), whose storage are
  165.  * consequentely released.
  166.  */
  167. void
  168. push_file (FILE *fp, const char *title)
  169. {
  170.   input_block *i;
  171.  
  172.   if (next != NULL)
  173.     {
  174.       obstack_free (current_input, next);
  175.       next = NULL;
  176.     }
  177.  
  178.   if (debug_level & DEBUG_TRACE_INPUT)
  179.     debug_message ("input read from %s", title);
  180.  
  181.   i = (input_block *) obstack_alloc (current_input,
  182.                      sizeof (struct input_block));
  183.   i->type = INPUT_FILE;
  184.  
  185.   i->u.u_f.name = current_file;
  186.   i->u.u_f.lineno = current_line;
  187.   i->u.u_f.out_lineno = output_current_line;
  188.   i->u.u_f.advance_line = start_of_input_line;
  189.   current_file = obstack_copy0 (current_input, title, strlen (title));
  190.   current_line = 1;
  191.   output_current_line = -1;
  192.  
  193.   i->u.u_f.file = fp;
  194.   i->prev = isp;
  195.   isp = i;
  196. }
  197.  
  198. /*
  199.  * push_macro () pushes a builtin macros definition on the input stack.  If
  200.  * next is non-NULL, this push invalidates a call to push_string_init (),
  201.  * whose storage are consequentely released.
  202.  */
  203. void
  204. push_macro (builtin_func *func, boolean traced)
  205. {
  206.   input_block *i;
  207.  
  208.   if (next != NULL)
  209.     {
  210.       obstack_free (current_input, next);
  211.       next = NULL;
  212.     }
  213.  
  214.   i = (input_block *) obstack_alloc (current_input,
  215.                      sizeof (struct input_block));
  216.   i->type = INPUT_MACRO;
  217.  
  218.   i->u.u_m.func = func;
  219.   i->u.u_m.traced = traced;
  220.   i->prev = isp;
  221.   isp = i;
  222. }
  223.  
  224. /*
  225.  * First half of push_string ().  The pointer next points to the new
  226.  * input_block.
  227.  */
  228. struct obstack *
  229. push_string_init (void)
  230. {
  231.   if (next != NULL)
  232.     internal_error ("recursive push_string!");
  233.  
  234.   next = (input_block *) obstack_alloc (current_input,
  235.                         sizeof (struct input_block));
  236.   next->type = INPUT_STRING;
  237.   return current_input;
  238. }
  239.  
  240. /*
  241.  * Last half of push_string ().  If next is now NULL, a call to
  242.  * push_file () has invalidated the previous call to push_string_init (),
  243.  * so we just give up.  If the new object is void, we do not push it.
  244.  * The function push_string_finish () returns a pointer to the finished
  245.  * object.  This pointer is only for temporary use, since reading the
  246.  * next token might release the memory used for the object.
  247.  */
  248. char *
  249. push_string_finish (void)
  250. {
  251.   char *ret = NULL;
  252.  
  253.   if (next == NULL)
  254.     return NULL;
  255.  
  256.   if (obstack_object_size (current_input) > 0)
  257.     {
  258.       obstack_1grow (current_input, '\0');
  259.       next->u.u_s.string = obstack_finish (current_input);
  260.       next->prev = isp;
  261.       isp = next;
  262.       ret = isp->u.u_s.string;    /* for immediate use only */
  263.     }
  264.   else
  265.     obstack_free (current_input, next); /* people might leave garbage on it. */
  266.   next = NULL;
  267.   return ret;
  268. }
  269.  
  270. /*
  271.  * The function push_wrapup () pushes a string on the wrapup stack.  When
  272.  * he normal input stack gets empty, the wrapup stack will become the
  273.  * input stack, and push_string () and push_file () will operate on
  274.  * wrapup_stack.  Push_wrapup should be done as push_string (), but this
  275.  * will suffice, as long as arguments to m4_m4wrap () are moderate in
  276.  * size.
  277.  */
  278. void
  279. push_wrapup (char *s)
  280. {
  281.   input_block *i = (input_block *) obstack_alloc (&wrapup_stack,
  282.                           sizeof (struct input_block));
  283.   i->prev = wsp;
  284.   i->type = INPUT_STRING;
  285.   i->u.u_s.string = obstack_copy0 (&wrapup_stack, s, strlen (s));
  286.   wsp = i;
  287. }
  288.  
  289.  
  290.  
  291. /*
  292.  * The function pop_input () pops one level of input sources.  If the
  293.  * popped input_block is a file, current_file and current_line are reset
  294.  * to the saved values before the memory for the input_block are
  295.  * released.
  296.  */
  297. static void
  298. pop_input (void)
  299. {
  300.   input_block *tmp = isp->prev;
  301.  
  302.   switch (isp->type)
  303.     {
  304.     case INPUT_STRING:
  305.     case INPUT_MACRO:
  306.       break;
  307.     case INPUT_FILE:
  308.       if (debug_level & DEBUG_TRACE_INPUT)
  309.     debug_message ("input reverted to %s, line %d",
  310.                isp->u.u_f.name, isp->u.u_f.lineno);
  311.  
  312.       fclose (isp->u.u_f.file);
  313.       current_file = isp->u.u_f.name;
  314.       current_line = isp->u.u_f.lineno;
  315.       output_current_line = isp->u.u_f.out_lineno;
  316.       start_of_input_line = isp->u.u_f.advance_line;
  317.       if (tmp != NULL)
  318.     output_current_line = -1;
  319.       break;
  320.     default:
  321.       internal_error ("Input stack botch in pop_input ()");
  322.       break;
  323.     }
  324.   obstack_free (current_input, isp);
  325.   next = NULL;            /* might be set in push_string_init () */
  326.  
  327.   isp = tmp;
  328. }
  329.  
  330. /*
  331.  * To switch input over to the wrapup stack, main () calls pop_wrapup ().
  332.  * Since wrapup text can install new wrapup text, pop_wrapup () returns
  333.  * FALSE when there is no wrapup text on the stack, and TRUE otherwise.
  334.  */
  335. boolean
  336. pop_wrapup (void)
  337. {
  338.   if (wsp == NULL)
  339.     return FALSE;
  340.  
  341.   current_input = &wrapup_stack;
  342.   isp = wsp;
  343.   wsp = NULL;
  344.  
  345.   return TRUE;
  346. }
  347.  
  348. /*
  349.  * When a MACRO token is seen, next_token () uses get_macro_func () to
  350.  * retrieve the value of the function pointer.
  351.  */
  352. static void
  353. init_macro_token (token_data *td)
  354. {
  355.   if (isp->type != INPUT_MACRO)
  356.     internal_error ("Bad call to get_macro_func ()");
  357.  
  358.   TOKEN_DATA_TYPE (td) = TOKEN_FUNC;
  359.   TOKEN_DATA_FUNC (td) = isp->u.u_m.func;
  360.   TOKEN_DATA_FUNC_TRACED (td) = isp->u.u_m.traced;
  361. }
  362.  
  363.  
  364. /*
  365.  * Low level input is done a character at a time.  The function
  366.  * peek_input () is used to look at the next character in the input
  367.  * stream.  At any given time, it reads from the input_block on the top
  368.  * of the current input stack.
  369.  */
  370. int
  371. peek_input (void)
  372. {
  373.   register int ch;
  374.  
  375.   while (1)
  376.     {
  377.       if (isp == NULL)
  378.     return CHAR_EOF;
  379.  
  380.       switch (isp->type)
  381.     {
  382.     case INPUT_STRING:
  383.       ch = isp->u.u_s.string[0];
  384.       if (ch != '\0')
  385.         return ch;
  386.       break;
  387.     case INPUT_FILE:
  388.       ch = getc (isp->u.u_f.file);
  389.       if (ch != EOF)
  390.         {
  391.           ungetc (ch, isp->u.u_f.file);
  392.           return ch;
  393.         }
  394.       break;
  395.     case INPUT_MACRO:
  396.       return CHAR_MACRO;
  397.     default:
  398.       internal_error ("Input stack botch in peek_input ()");
  399.       break;
  400.     }
  401.       /* End of input source --- pop one level.  */
  402.       pop_input ();
  403.     }
  404. }
  405.  
  406. /*
  407.  * The function next_char () is used to read and advance the input to the
  408.  * next character.  It also manages line numbers for error messages, so
  409.  * they do not get wrong, due to lookahead.  The token consisting of a
  410.  * newline alone is taken as belonging to the line it ends, and the
  411.  * current line number is not incremented until the next character is
  412.  * read.
  413.  */
  414. static int
  415. next_char (void)
  416. {
  417.   register int ch;
  418.  
  419.   if (start_of_input_line)
  420.     {
  421.       start_of_input_line = FALSE;
  422.       current_line++;
  423.     }
  424.  
  425.   while (1)
  426.     {
  427.       if (isp == NULL)
  428.     return CHAR_EOF;
  429.  
  430.       switch (isp->type)
  431.     {
  432.     case INPUT_STRING:
  433.       ch = *isp->u.u_s.string++;
  434.       if (ch != '\0')
  435.         return ch;
  436.       break;
  437.     case INPUT_FILE:
  438.       ch = getc (isp->u.u_f.file);
  439.       if (ch != EOF)
  440.         {
  441.           if (ch == '\n')
  442.         start_of_input_line = TRUE;
  443.           return ch;
  444.         }
  445.       break;
  446.     case INPUT_MACRO:
  447.       pop_input ();        /* INPUT_MACRO input sources has only one token */
  448.       return CHAR_MACRO;
  449.       break;
  450.     default:
  451.       internal_error ("Input stack botch in advance_input ()");
  452.       break;
  453.     }
  454.       /* End of input source --- pop one level.  */
  455.       pop_input ();
  456.     }
  457. }
  458.  
  459. /*
  460.  * skip_line () simply discards all immediately following characters,
  461.  * upto the first newline.  It is only used from m4_dnl ().
  462.  */
  463. void
  464. skip_line (void)
  465. {
  466.   int ch;
  467.  
  468.   while ((ch = next_char ()) != CHAR_EOF && ch != '\n')
  469.     ;
  470. }
  471.  
  472.  
  473. /*
  474.  * This function is for matching a string against a prefix of the input
  475.  * stream.  If the string matches the input, the input is discarded,
  476.  * otherwise the characters read are pushed back again.  The functin is
  477.  * used only when multicharacter quotes or comment delimiters are used.
  478.  */
  479.  
  480. static int
  481. match_input (char *s)
  482. {
  483.   int n;            /* number of characters matched */
  484.   int ch;            /* input character */
  485.   char *t;
  486.  
  487.   ch = peek_input ();
  488.   if (ch != *s)
  489.     return 0;            /* fail */
  490.   (void) next_char ();
  491.  
  492.   if (s[1] == '\0')
  493.     return 1;            /* short match */
  494.  
  495.   for (n = 1, t = s++; (ch = peek_input ()) == *s++; n++)
  496.     {
  497.       (void) next_char ();
  498.       if (*s == '\0')        /* long match */
  499.     return 1;
  500.     }
  501.  
  502.   /* Failed, push back input.  */
  503.   obstack_grow (push_string_init (), t, n);
  504.   push_string_finish ();
  505.   return 0;
  506. }
  507.  
  508. /*
  509.  * The macro MATCH() is used to match a string against the input.  The
  510.  * first character is handled inline, for speed.  Hopefully, this will
  511.  * not hurt efficiency too much when single character quotes and comment
  512.  * delimiters are used.
  513.  */
  514. #define MATCH(ch, s) \
  515.   ((s)[0] == (ch) \
  516.    && (ch) != '\0' \
  517.    && ((s)[1] == '\0' \
  518.        || (match_input ((s) + 1) ? (ch) = peek_input (), 1 : 0)))
  519.  
  520.  
  521. /*
  522.  * Inititialise input stacks, and quote/comment characters.
  523.  */
  524. void
  525. input_init (void)
  526. {
  527.   current_file = "NONE";
  528.   current_line = 0;
  529.  
  530.   obstack_init (&token_stack);
  531.   obstack_init (&input_stack);
  532.   obstack_init (&wrapup_stack);
  533.  
  534.   current_input = &input_stack;
  535.  
  536.   obstack_1grow (&token_stack, '\0');
  537.   token_bottom = obstack_finish (&token_stack);
  538.  
  539.   isp = NULL;
  540.   wsp = NULL;
  541.   next = NULL;
  542.  
  543.   start_of_input_line = FALSE;
  544.  
  545.   set_quotes (NULL, NULL);
  546.   set_comment (NULL, NULL);
  547. }
  548.  
  549.  
  550. /*
  551.  * Functions for setting quotes and comment delimiters.  Used by
  552.  * m4_changecom () and m4_changequote ().
  553.  */
  554.  
  555. void
  556. set_quotes (char *lq, char *rq)
  557. {
  558.   if (lquote != def_lquote)
  559.     xfree (lquote);
  560.   if (rquote != def_rquote)
  561.     xfree (rquote);
  562.  
  563.   lquote = (lq == NULL) ? def_lquote : xstrdup (lq);
  564.   rquote = (rq == NULL) ? def_rquote : xstrdup (rq);
  565.  
  566.   len_lquote = strlen (lquote);
  567.   len_rquote = strlen (rquote);
  568. }
  569.  
  570. void
  571. set_comment (char *bc, char *ec)
  572. {
  573.   if (bcomm != def_bcomm)
  574.     xfree (bcomm);
  575.   if (ecomm != def_ecomm)
  576.     xfree (ecomm);
  577.  
  578.   bcomm = (bc == NULL) ? def_bcomm : xstrdup (bc);
  579.   ecomm = (ec == NULL) ? def_ecomm : xstrdup (ec);
  580.  
  581.   len_bcomm = strlen (bcomm);
  582.   len_ecomm = strlen (ecomm);
  583. }
  584.  
  585.  
  586. /*
  587.  * Parse and return a single token from the input stream.  A token can
  588.  * either be TOKEN_EOF, if the input_stack is empty; it can be
  589.  * TOKEN_STRING for a quoted string; TOKEN_WORD for something that is a
  590.  * potential macro name; and TOKEN_SIMPLE for any single character that
  591.  * is not a part of any of the previous types.
  592.  *
  593.  * Next_token () return the token type, and passes back a pointer to the
  594.  * token data through TD.  The token text is collected on the obstack
  595.  * token_stack, which never contains more than one token text at a time.
  596.  * The storage pointed to by the fields in TD is therefore subject to
  597.  * change the next time next_token () is called.
  598.  */
  599.  
  600. token_type
  601. next_token (token_data *td)
  602. {
  603.   int ch;
  604.   int quote_level;
  605.   token_type type;
  606.  
  607.   obstack_free (&token_stack, token_bottom);
  608.   obstack_1grow (&token_stack, '\0');
  609.   token_bottom = obstack_finish (&token_stack);
  610.  
  611.   ch = peek_input ();
  612.   if (ch == CHAR_EOF)
  613.     {
  614.       return TOKEN_EOF;
  615. #ifdef DEBUG_INPUT
  616.       fprintf (stderr, "next_token -> EOF\n");
  617. #endif
  618.     }
  619.   if (ch == CHAR_MACRO)
  620.     {
  621.       init_macro_token (td);
  622.       (void) next_char ();
  623.       return TOKEN_MACDEF;
  624.     }
  625.  
  626.   (void) next_char ();
  627.   if (MATCH (ch, bcomm))
  628.     {
  629.  
  630.       obstack_grow (&token_stack, bcomm, len_bcomm);
  631.       while ((ch = next_char ()) != CHAR_EOF && !MATCH (ch, ecomm))
  632.     obstack_1grow (&token_stack, ch);
  633.       if (ch != CHAR_EOF)
  634.     obstack_grow (&token_stack, ecomm, len_ecomm);
  635.       type = TOKEN_STRING;
  636.  
  637.     }
  638.   else if (isalpha (ch) || ch == '_')
  639.     {
  640.  
  641.       obstack_1grow (&token_stack, ch);
  642.       while ((ch = peek_input ()) != CHAR_EOF && (isalnum (ch) || ch == '_'))
  643.     {
  644.       obstack_1grow (&token_stack, ch);
  645.       (void) next_char ();
  646.     }
  647.       type = TOKEN_WORD;
  648.  
  649.     }
  650.   else if (!MATCH (ch, lquote))
  651.     {
  652.  
  653.       type = TOKEN_SIMPLE;
  654.       obstack_1grow (&token_stack, ch);
  655.  
  656.     }
  657.   else
  658.     {
  659.  
  660.       quote_level = 1;
  661.       while (1)
  662.     {
  663.       ch = next_char ();
  664.       if (ch == CHAR_EOF)
  665.         fatal ("EOF in string");
  666.  
  667.       if (MATCH (ch, rquote))
  668.         {
  669.           if (--quote_level == 0)
  670.         break;
  671.           obstack_grow (&token_stack, rquote, len_rquote);
  672.         }
  673.       else if (MATCH (ch, lquote))
  674.         {
  675.           quote_level++;
  676.           obstack_grow (&token_stack, lquote, len_lquote);
  677.         }
  678.       else
  679.         obstack_1grow (&token_stack, ch);
  680.     }
  681.       type = TOKEN_STRING;
  682.     }
  683.  
  684.   obstack_1grow (&token_stack, '\0');
  685.  
  686.   TOKEN_DATA_TYPE (td) = TOKEN_TEXT;
  687.   TOKEN_DATA_TEXT (td) = obstack_finish (&token_stack);
  688. #ifdef DEBUG_INPUT
  689.   fprintf (stderr, "next_token -> %d (%s)\n", type, TOKEN_DATA_TEXT (td));
  690. #endif
  691.   return type;
  692. }
  693.  
  694.  
  695. #ifdef DEBUG_INPUT
  696.  
  697. static void
  698. print_token (char *s, token_type t, token_data *td)
  699. {
  700.   fprintf (stderr, "%s: ", s);
  701.   switch (t)
  702.     {                /* TOKSW */
  703.     case TOKEN_SIMPLE:
  704.       fprintf (stderr, "char:");
  705.       break;
  706.     case TOKEN_WORD:
  707.       fprintf (stderr, "word:");
  708.       break;
  709.     case TOKEN_STRING:
  710.       fprintf (stderr, "string:");
  711.       break;
  712.     case TOKEN_MACDEF:
  713.       fprintf (stderr, "macro: 0x%x\n", TOKEN_DATA_FUNC (td));
  714.       break;
  715.     case TOKEN_EOF:
  716.       fprintf (stderr, "eof\n");
  717.       break;
  718.     }
  719.   fprintf (stderr, "\t\"%s\"\n", TOKEN_DATA_TEXT (td));
  720. }
  721.  
  722. static void
  723. lex_debug (void)
  724. {
  725.   token_type t;
  726.   token_data td;
  727.  
  728.   while ((t = next_token (&td)) != NULL)
  729.     print_token ("lex", t, &td);
  730. }
  731. #endif
  732.